#ifndef FILEHANDLER_H
#define FILEHANDLER_H

#include <QString>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QFile>
#include <QFileInfo>
#include <QMutex>
#include <QHash>
#include <QDateTime>
#include <QTimer>
#include <QObject>
#include "../utils/errorhandler.h"

/**
 * @brief 文件操作处理器
 * 
 * 提供JSON文件的读写、备份、锁定等功能
 * 确保数据文件的安全性和一致性
 */

namespace RestaurantSystem {

/**
 * @brief 文件锁类
 */
class FileLock {
public:
    explicit FileLock(const QString& filePath);
    ~FileLock();
    
    bool tryLock(int timeoutMs = 3000);
    void unlock();
    bool isLocked() const { return m_isLocked; }
    
private:
    QString m_filePath;
    QString m_lockFilePath;
    bool m_isLocked;
};

/**
 * @brief 文件操作处理器类
 */
class FileHandler : public QObject {
    Q_OBJECT
    
public:
    explicit FileHandler(QObject* parent = nullptr);
    ~FileHandler();
    
    /**
     * @brief 读取JSON文件
     * @param filePath 文件路径
     * @param result 读取结果
     * @return 操作结果
     */
    FileOperationResult readJsonFile(const QString& filePath, QJsonObject& result);
    
    /**
     * @brief 写入JSON文件
     * @param filePath 文件路径
     * @param data JSON数据
     * @param createBackup 是否创建备份
     * @return 操作结果
     */
    FileOperationResult writeJsonFile(const QString& filePath, const QJsonObject& data, bool createBackup = true);
    
    /**
     * @brief 读取JSON数组文件
     * @param filePath 文件路径
     * @param result 读取结果
     * @return 操作结果
     */
    FileOperationResult readJsonArray(const QString& filePath, QJsonArray& result);
    
    /**
     * @brief 写入JSON数组文件
     * @param filePath 文件路径
     * @param data JSON数组数据
     * @param createBackup 是否创建备份
     * @return 操作结果
     */
    FileOperationResult writeJsonArray(const QString& filePath, const QJsonArray& data, bool createBackup = true);
    
    /**
     * @brief 创建文件备份
     * @param filePath 源文件路径
     * @return 备份文件路径，失败返回空字符串
     */
    QString createBackup(const QString& filePath);
    
    /**
     * @brief 恢复文件备份
     * @param filePath 目标文件路径
     * @param backupPath 备份文件路径
     * @return 操作是否成功
     */
    bool restoreBackup(const QString& filePath, const QString& backupPath);
    
    /**
     * @brief 验证JSON文件格式
     * @param filePath 文件路径
     * @param errorString 错误信息输出
     * @return 验证结果
     */
    bool validateJsonFile(const QString& filePath, QString& errorString);
    
    /**
     * @brief 获取文件信息
     * @param filePath 文件路径
     * @return 文件信息
     */
    QFileInfo getFileInfo(const QString& filePath);
    
    /**
     * @brief 确保目录存在
     * @param dirPath 目录路径
     * @return 操作是否成功
     */
    bool ensureDirectoryExists(const QString& dirPath);
    
    /**
     * @brief 清理旧备份文件
     * @param filePath 主文件路径
     * @param maxBackups 保留的最大备份数量
     */
    void cleanupOldBackups(const QString& filePath, int maxBackups = 10);
    
    /**
     * @brief 获取可用的备份文件列表
     * @param filePath 主文件路径
     * @return 备份文件列表(按时间排序，最新的在前)
     */
    QStringList getBackupFiles(const QString& filePath);
    
    /**
     * @brief 设置自动备份启用状态
     * @param enabled 是否启用
     */
    void setAutoBackupEnabled(bool enabled) { m_autoBackupEnabled = enabled; }
    
    /**
     * @brief 设置最大备份文件数量
     * @param maxBackups 最大数量
     */
    void setMaxBackupFiles(int maxBackups) { m_maxBackupFiles = maxBackups; }
    
    /**
     * @brief 检查文件是否存在且可读
     * @param filePath 文件路径
     * @return 检查结果
     */
    bool isFileReadable(const QString& filePath);
    
    /**
     * @brief 检查文件是否可写
     * @param filePath 文件路径
     * @return 检查结果
     */
    bool isFileWritable(const QString& filePath);
    
    /**
     * @brief 获取文件大小
     * @param filePath 文件路径
     * @return 文件大小(字节)，失败返回-1
     */
    qint64 getFileSize(const QString& filePath);
    
public slots:
    /**
     * @brief 执行定期清理任务
     */
    void performMaintenance();
    
private slots:
    void onMaintenanceTimer();
    
private:
    /**
     * @brief 解析JSON数据
     * @param data 原始数据
     * @param document JSON文档输出
     * @param errorString 错误信息输出
     * @return 解析是否成功
     */
    bool parseJsonData(const QByteArray& data, QJsonDocument& document, QString& errorString);
    
    /**
     * @brief 生成备份文件路径
     * @param originalPath 原始文件路径
     * @return 备份文件路径
     */
    QString generateBackupPath(const QString& originalPath);
    
    /**
     * @brief 安全写入文件(使用临时文件)
     * @param filePath 目标文件路径
     * @param data 数据
     * @return 操作结果
     */
    FileOperationResult safeWriteFile(const QString& filePath, const QByteArray& data);
    
    /**
     * @brief 获取文件锁
     * @param filePath 文件路径
     * @return 文件锁对象
     */
    std::unique_ptr<FileLock> getFileLock(const QString& filePath);

private:
    bool m_autoBackupEnabled;
    int m_maxBackupFiles;
    QTimer* m_maintenanceTimer;
    QHash<QString, QDateTime> m_fileModificationTimes; // 缓存文件修改时间
    mutable QMutex m_mutex; // 保护内部数据结构
};

/**
 * @brief RAII文件锁管理器
 */
class FileLocker {
public:
    explicit FileLocker(const QString& filePath, int timeoutMs = 3000);
    ~FileLocker();
    
    bool isLocked() const { return m_lock && m_lock->isLocked(); }
    
private:
    std::unique_ptr<FileLock> m_lock;
};

/**
 * @brief 文件操作辅助函数
 */
namespace FileUtils {
    /**
     * @brief 安全地读取文件内容
     */
    QByteArray safeReadFile(const QString& filePath, FileOperationResult& result);
    
    /**
     * @brief 安全地写入文件内容
     */
    FileOperationResult safeWriteFile(const QString& filePath, const QByteArray& data);
    
    /**
     * @brief 创建目录(递归)
     */
    bool createDirectory(const QString& dirPath);
    
    /**
     * @brief 复制文件
     */
    bool copyFile(const QString& sourcePath, const QString& destPath);
    
    /**
     * @brief 移动文件
     */
    bool moveFile(const QString& sourcePath, const QString& destPath);
    
    /**
     * @brief 删除文件
     */
    bool removeFile(const QString& filePath);
    
    /**
     * @brief 获取文件的MD5哈希值
     */
    QString getFileMD5(const QString& filePath);
    
    /**
     * @brief 比较两个文件是否相同
     */
    bool filesAreEqual(const QString& file1, const QString& file2);
}

} // namespace RestaurantSystem

#endif // FILEHANDLER_H
